<template>
    <div class="home">
        <header>
            <el-button @click="undo">撤消</el-button>
            <el-button @click="redo">重做</el-button>
            <label for="input" class="insert">插入图片</label>
            <input type="file" @change="handleFileChange" id="input" hidden />
            <el-button @click="preview" style="margin-left: 10px;">预览</el-button>
            <el-button @click="save">保存</el-button>
            <el-button @click="clearCanvas">清空画布</el-button>
            <div class="canvas-config">
                <span>画布大小</span>
                <input v-model="canvasStyleData.width">
                <span>*</span>
                <input v-model="canvasStyleData.height">
            </div>
        </header>

        <main>
            <!-- 左侧组件列表 -->
            <section class="left">
                <ComponentList />
            </section>
            <!-- 中间画布 -->
            <section class="center">
                <div class="content" @drop="handleDrop" @dragover="handleDragOver" @click="deselectCurComponent">
                    <Editor />
                </div>
            </section>
            <!-- 右侧属性列表 -->
            <section class="right">
                <el-tabs v-model="activeName">
                    <el-tab-pane label="属性" name="attr">
                        <AttrList v-if="curComponent" />
                        <p v-else class="placeholder">请选择组件</p>
                    </el-tab-pane>
                    <el-tab-pane label="动画" name="animation">
                        <div v-if="curComponent" class="div-animation">
                            <el-button @click="isShowAnimation = true">添加动画</el-button>
                            <el-button @click="previewAnimate">预览动画</el-button>
                            <div>
                                <el-tag
                                    v-for="(tag, index) in curComponent.animations"
                                    :key="index"
                                    closable
                                    @close="removeAnimation(index)"
                                >
                                    {{ tag.label }}
                                </el-tag>
                            </div>
                        </div>
                        <p v-else class="placeholder">请选择组件</p>
                    </el-tab-pane>
                    <el-tab-pane label="事件" name="events">
                        <div v-if="curComponent" class="div-events">
                            <el-button @click="isShowEvent = true">添加事件</el-button>
                            <div>
                                <el-tag
                                    v-for="event in Object.keys(curComponent.events)"
                                    :key="event"
                                    closable
                                    @close="removeEvent(event)"
                                >
                                   {{ event }}
                                </el-tag>
                            </div>
                        </div>
                        <p v-else class="placeholder">请选择组件</p>
                    </el-tab-pane>
                </el-tabs>
            </section>
        </main>

        <!-- 选择动画 -->
        <Modal v-model="isShowAnimation">
            <el-tabs v-model="animationActiveName">
                <el-tab-pane v-for="item in animationClassData" :key="item.label" :label="item.label" :name="item.label">
                    <el-scrollbar class="animate-container">
                        <div
                            class="animate"
                            v-for="(animate, index) in item.children"
                            :key="index"
                            @mouseover="hoverPreviewAnimate = animate.value"
                            @click="addAnimation(animate)"
                        >
                            <div :class="[hoverPreviewAnimate === animate.value && animate.value + ' animated']">
                                {{ animate.label }}
                            </div>
                        </div>
                    </el-scrollbar>
                </el-tab-pane>
            </el-tabs>
        </Modal>

        <!-- 选择事件 -->
        <Modal v-model="isShowEvent">
            <el-tabs v-model="eventActiveName">
                <el-tab-pane v-for="item in eventList" :key="item.key" :label="item.label" :name="item.key" style="padding: 0 20px">
                    <el-input v-if="item.key == 'redirect'" v-model="item.param" type="textarea" placeholder="请输入完整的 URL" />
                    <el-input v-if="item.key == 'alert'" v-model="item.param" type="textarea" placeholder="请输入要 alert 的内容" />
                    <el-button style="margin-top: 20px;" @click="addEvent(item.key, item.param)">确定</el-button>
                </el-tab-pane>
            </el-tabs>
        </Modal>
        
        <!-- 预览 -->
        <Preview v-model="isShowPreview" @change="handlePreviewChange" />
    </div>
</template>

<script>
import Modal from '@/components/Modal'
import Editor from '@/components/Editor/index'
import ComponentList from '@/components/ComponentList' // 左侧列表组件
import AttrList from '@/components/AttrList' // 右侧属性列表
import componentList from '@/custom-component/component-list' // 左侧列表数据
import { deepCopy } from '@/utils/utils'
import { mapState } from 'vuex'
import toast from '@/utils/toast'
import animationClassData from '@/utils/animationClassData'
import eventBus from '@/utils/eventBus'
import Preview from '@/components/Editor/Preview'
import { eventList } from '@/utils/events'
import generateID from '@/utils/generateID'

export default {
    components: { Editor, ComponentList, AttrList, Modal, Preview },
    data() {
        return {
            isShowPreview: false,
            isShowAnimation: false,
            isShowEvent: false,
            activeName: 'attr',
            animationClassData,
            animationActiveName: '进入',
            showAnimatePanel: false,
            reSelectAnimateIndex: undefined,
            hoverPreviewAnimate: '',
            eventURL: '',
            eventActiveName: 'redirect',
            eventList,
        }
    },
    computed: mapState([
        'componentData',
        'curComponent',
        'canvasStyleData',
    ]),
    created() {
        // 用保存的数据恢复画布
        if (localStorage.getItem('canvasData')) {
            this.$store.commit('setComponentData', this.resetID(JSON.parse(localStorage.getItem('canvasData'))))
        }

        if (localStorage.getItem('canvasStyle')) {
            this.$store.commit('setCanvasStyle', JSON.parse(localStorage.getItem('canvasStyle')))
        }
    },
    methods: {
        resetID(data) {
            data.forEach(item => {
                item.id = generateID()
            })

            return data
        },

        handleDrop(e) {
            e.preventDefault()
            e.stopPropagation()
            const component = deepCopy(componentList[e.dataTransfer.getData('index')])
            component.style.top = e.offsetY
            component.style.left = e.offsetX
            component.id = generateID()
            this.$store.commit('addComponent', component)
            this.$store.commit('recordSnapshot')
        },

        handleDragOver(e) {
            e.preventDefault()
            e.dataTransfer.dropEffect = 'copy'
        },

        deselectCurComponent() {
            this.$store.commit('setCurComponent', { component: null, zIndex: null })
            this.$store.commit('hideContexeMenu')
        },

        undo() {
            this.$store.commit('undo')
        },

        redo() {
            this.$store.commit('redo')
        },

        handleFileChange(e) {
            const file = e.target.files[0]
            if (!file.type.includes('image')) {
                toast('只能插入图片', 'error')
                return
            }

            const reader = new FileReader()
            reader.onload = (res) => {
                const fileResult = res.target.result
                const img = new Image()
                img.onload = () => {
                    this.$store.commit('addComponent', {
                        id: generateID(),
                        component: 'Picture', 
                        label: '图片', 
                        icon: '',
                        propValue: fileResult,
                        animations: [],
                        events: [],
                        style: {
                            top: 0,
                            left: 0,
                            width: img.width,
                            height: img.height,
                            rotate: '',
                        },
                    })
                }

                img.src = fileResult
            }

            reader.readAsDataURL(file)
        },

        addAnimation(animate) {
            this.$store.commit('addAnimation', animate)
            this.isShowAnimation = false
        },

        previewAnimate() {
            eventBus.$emit('runAnimation')
        },

        removeAnimation(index) {
            this.$store.commit('removeAnimation', index)
        },

        preview() {
            this.isShowPreview = true
            this.$store.commit('setEditMode', 'read')
        },

        handlePreviewChange() {
            this.$store.commit('setEditMode', 'edit')
        },

        save() {
            localStorage.setItem('canvasData', JSON.stringify(this.componentData))
            localStorage.setItem('canvasStyle', JSON.stringify(this.canvasStyleData))
            this.$message.success('保存成功')
        },

        clearCanvas() {
            this.$store.commit('setComponentData', [])
        },

        addEvent(event, param) {
            this.isShowEvent = false
            this.$store.commit('addEvent', { event, param })
        },

        removeEvent(event) {
            this.$store.commit('removeEvent', event)
        },
    },
}
</script>

<style lang="scss">
.home {
    height: 100vh;
    background: #fff;

    header {
        height: 64px;
        line-height: 64px;
        background: #fff;
        border-bottom: 1px solid #ddd;
    }

    main {
        height: calc(100% - 64px);
        position: relative;

        .left {
            position: absolute;
            height: 100%;
            width: 200px;
            left: 0;
            top: 0;
            padding-top: 10px;
        }

        .right {
            position: absolute;
            height: 100%;
            width: 262px;
            right: 0;
            top: 0;
        }

        .center {
            margin-left: 200px;
            margin-right: 262px;
            background: #f5f5f5;
            height: 100%;
            overflow: auto;
            padding: 20px;

            .content {
                height: 100%;
                overflow: auto;
                display: flex;
                align-items: center;
                justify-content: center;
            }
        }
    }

    .placeholder {
        text-align: center;
        color: #333;
    }

    .el-scrollbar__view {
        display: flex;
        align-items: center;
        flex-wrap: wrap;
        padding-left: 14px;

        .animate > div {
            width: 100px;
            height: 60px;
            background: #f5f8fb;
            display: flex;
            align-items: center;
            justify-content: center;
            margin: 0 12px;
            margin-bottom: 10px;
            font-size: 12px;
            color: #333;
            border-radius: 3px;
            user-select: none;
            cursor: pointer;
        }
    }

    .el-tag {
        display: block;
        width: 50%;
        margin: auto;
        margin-bottom: 10px;
    }

    .div-animation {
        text-align: center;

        & > div {
            margin-top: 20px;
        }
    }

    .insert {
        display: inline-block;
        line-height: 1;
        white-space: nowrap;
        cursor: pointer;
        background: #FFF;
        border: 1px solid #DCDFE6;
        color: #606266;
        -webkit-appearance: none;
        text-align: center;
        box-sizing: border-box;
        outline: 0;
        margin: 0;
        transition: .1s;
        font-weight: 500;
        padding: 9px 15px;
        font-size: 12px;
        border-radius: 3px;
        margin-left: 10px;

        &:active {
            color: #3a8ee6;
            border-color: #3a8ee6;
            outline: 0;
        }

        &:hover {
            background-color: #ecf5ff;
            color: #3a8ee6;
        }
    }

    .canvas-config {
        display: inline-block;
        margin-left: 10px;
        font-size: 14px;
        color: #606266;

        input {
            width: 50px;
            margin-left: 10px;
            outline: none;
            padding: 0 5px;
            border: 1px solid #ddd;
            color: #606266;
        }

        span {
            margin-left: 10px;
        }
    }

    .div-events {
        text-align: center;
        padding: 0 20px;
        
        .el-button {
            display: inline-block;
            margin-bottom: 10px;
        }
    }
}
</style>
